package sdk

import (
	"log"

	"gitee.com/linxing_3/youye-core/config/source"
	"gitee.com/linxing_3/youye-core/config/source/env"
	"gitee.com/linxing_3/youye-core/config/source/file"
	"gitee.com/linxing_3/youye-core/sdk/application"
	"gitee.com/linxing_3/youye-core/sdk/config"
	"gitee.com/linxing_3/youye-core/sdk/pkg/captcha"
	"gitee.com/linxing_3/youye-core/sdk/pkg/cronjob"
	"gitee.com/linxing_3/youye-core/sdk/pkg/database"
	"gitee.com/linxing_3/youye-core/sdk/pkg/logger"

	"github.com/gin-gonic/gin"
)

var App application.IApplication = application.NewConfig()

func NewApp(configPath string, envprefix string) (application.IApplication, error) {
	err := config.Setup([]source.Source{
		file.NewSource(file.WithPath(configPath)),
		env.NewSource(
			env.WithPrefix(envprefix),
			env.WithStrippedPrefix(envprefix),
		),
	})
	if err != nil {
		return nil, err
	}

	globalConf := config.GetConfig()
	App.SetConfig(globalConf)

	// if logger.DefaultLogger == nil {
	initLogger(globalConf)
	// }

	initDB(globalConf)

	if err := initCache(globalConf); err != nil {
		return nil, err
	}

	App.SetCrontab("*", cronjob.NewWithSeconds())

	if !config.LockerConfig.Empty() {
		lockerAdapter, err := config.LockerConfig.Setup()
		if err != nil {
			log.Fatalf("locker setup error, %s\n", err.Error())
		}
		App.SetLockerAdapter(lockerAdapter)
	}

	ginEngine := gin.New()
	if config.ApplicationConfig.Mode == gin.DebugMode {
		gin.SetMode(gin.DebugMode)
	} else {
		gin.SetMode(gin.ReleaseMode)
	}
	ginEngine.Use(gin.Recovery())
	App.SetEngine(ginEngine)

	return App, nil
}

func initLogger(conf *config.Config) {

	l := logger.SetupLogger(
		logger.WithType(conf.Logger.Type),
		logger.WithPath(conf.Logger.Path),
		logger.WithLevel(conf.Logger.Level),
		logger.WithStdout(conf.Logger.Stdout),
		logger.WithCap(conf.Logger.Cap),
		logger.WithCallSkip(conf.Logger.SkipCount),
	)

	App.SetLogger(l)
}

func initDB(conf *config.Config) {
	if conf.Database == nil || conf.Database.Driver == "" || conf.Database.Source == "" {
		return
	}
	dblog := App.GetLogger()
	if conf.Database != nil && conf.Database.Logger != nil {
		dblog = logger.SetupLogger(
			logger.WithType(conf.Database.Logger.Type),
			logger.WithPath(conf.Database.Logger.Path),
			logger.WithLevel(conf.Database.Logger.Level),
			logger.WithStdout(conf.Database.Logger.Stdout),
			logger.WithCap(conf.Database.Logger.Cap),
			logger.WithCallSkip(conf.Database.Logger.SkipCount),
		)
	}

	db, err := database.NewDatabase("*", conf.Database, dblog)
	if err != nil {
		log.Fatalf("database setup error, %s\n", err.Error())
	}
	App.SetDb("*", db)
}

func initCache(*config.Config) error {
	cache, err := config.CacheConfig.Setup()
	if err != nil {
		return err
	}
	captcha.SetStore(captcha.NewCacheStore(cache, 600))

	App.SetCacheAdapter(cache)
	return nil
}
